use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::sync::Arc;
use std::time::{Duration, SystemTime};
use tokio::sync::RwLock;
use tokio::time::sleep;
use thiserror::Error;
use tauri::{AppHandle, Emitter};

// EZK SIP library imports for call management
use sip_ua::{Call, RtcMediaBackend};
use sip_auth::{DigestCredentials, DigestUser};
use rtc::{
    sdp::{Codec, Codecs, SdpSession, SdpSessionConfig},
    OpenSslContext,
};
use rtc::sdp::{TransportType as RtcTransportType, RtcpMuxPolicy};
use sdp_types::{Direction, MediaType};

#[derive(Debug, Error)]
pub enum CallManagerError {
    #[error("Call setup failed: {0}")]
    CallSetupFailed(String),
    #[error("Call not found: {0}")]
    CallNotFound(String),
    #[error("Invalid call state: {0}")]
    InvalidCallState(String),
    #[error("SIP error: {0}")]
    SipError(String),
    #[error("Media error: {0}")]
    MediaError(String),
    #[error("Authentication error: {0}")]
    AuthenticationError(String),
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CallInfo {
    pub id: String,
    pub remote_number: String,
    pub remote_name: Option<String>,
    pub direction: CallDirection,
    pub status: CallStatus,
    pub start_time: Option<SystemTime>,
    pub duration: Option<Duration>,
}

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub enum CallDirection {
    Inbound,
    Outbound,
}

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub enum CallStatus {
    Ringing,
    Connected,
    Ended,
    Failed,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct IncomingCallInfo {
    pub call_id: String,
    pub caller_number: String,
    pub caller_name: Option<String>,
}

// Event structures for frontend communication
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct IncomingCallEvent {
    pub call_id: String,
    pub caller_number: String,
    pub caller_name: Option<String>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CallStatusEvent {
    pub call_id: String,
    pub status: CallStatus,
    pub duration: Option<u64>, // seconds
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AudioStatusEvent {
    pub call_id: String,
    pub muted: bool,
    pub volume_level: f32,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CallQualityMetrics {
    pub input_level: f32,
    pub output_level: f32,
    pub packet_loss_rate: f32,
    pub jitter: f32,
    pub round_trip_time: Option<u64>, // milliseconds
    pub packets_sent: u64,
    pub packets_received: u64,
    pub packets_lost: u64,
    pub bytes_sent: u64,
    pub bytes_received: u64,
}

impl Default for CallQualityMetrics {
    fn default() -> Self {
        Self {
            input_level: 0.0,
            output_level: 0.0,
            packet_loss_rate: 0.0,
            jitter: 0.0,
            round_trip_time: None,
            packets_sent: 0,
            packets_received: 0,
            packets_lost: 0,
            bytes_sent: 0,
            bytes_received: 0,
        }
    }
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CallQualityEvent {
    pub call_id: String,
    pub metrics: CallQualityMetrics,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CallDurationEvent {
    pub call_id: String,
    pub duration: u64, // seconds
}

// Internal call state for managing active calls
struct ActiveCall {
    info: CallInfo,
    sip_call: Option<Call<RtcMediaBackend>>,
    is_muted: bool,
    timeout_handle: Option<tokio::task::JoinHandle<()>>,
    duration_timer: Option<tokio::task::JoinHandle<()>>,
    quality_metrics: CallQualityMetrics,
}

#[derive(Clone)]
pub struct CallManager {
    active_calls: Arc<RwLock<HashMap<String, ActiveCall>>>,
    call_counter: Arc<RwLock<u32>>,
    app_handle: Arc<RwLock<Option<AppHandle>>>,
    call_history_manager: Arc<RwLock<Option<Arc<crate::call_history::CallHistoryManager>>>>,
}

impl CallManager {
    pub fn new() -> Self {
        Self {
            active_calls: Arc::new(RwLock::new(HashMap::new())),
            call_counter: Arc::new(RwLock::new(0)),
            app_handle: Arc::new(RwLock::new(None)),
            call_history_manager: Arc::new(RwLock::new(None)),
        }
    }

    pub async fn set_app_handle(&self, app_handle: AppHandle) {
        *self.app_handle.write().await = Some(app_handle);
    }

    pub async fn set_call_history_manager(&self, history_manager: Arc<crate::call_history::CallHistoryManager>) {
        *self.call_history_manager.write().await = Some(history_manager);
    }

    pub async fn make_call(
        &self, 
        number: String,
        sip_manager: Arc<crate::sip_manager::SipManager>,
        audio_manager: Arc<crate::audio_manager::AudioManager>
    ) -> Result<String, CallManagerError> {
        let mut counter = self.call_counter.write().await;
        *counter += 1;
        let call_id = format!("call_{}", *counter);
        drop(counter);

        log::info!("Making call to {} with ID: {}", number, call_id);

        // Create call info
        let call_info = CallInfo {
            id: call_id.clone(),
            remote_number: number.clone(),
            remote_name: None,
            direction: CallDirection::Outbound,
            status: CallStatus::Ringing,
            start_time: Some(SystemTime::now()),
            duration: None,
        };

        // Create active call entry
        let active_call = ActiveCall {
            info: call_info,
            sip_call: None,
            is_muted: false,
            timeout_handle: None,
            duration_timer: None,
            quality_metrics: CallQualityMetrics::default(),
        };

        self.active_calls.write().await.insert(call_id.clone(), active_call);

        // Emit call status event
        self.emit_call_status_event(CallStatusEvent {
            call_id: call_id.clone(),
            status: CallStatus::Ringing,
            duration: None,
        }).await;

        // Start the actual SIP call in a background task
        let call_manager = Arc::new(self.clone());
        let call_id_clone = call_id.clone();
        let number_clone = number.clone();
        let call_id_for_error = call_id.clone();
        
        tokio::spawn(async move {
            if let Err(e) = call_manager.initiate_sip_call(call_id_clone, number_clone, sip_manager, audio_manager).await {
                log::error!("Failed to initiate SIP call: {}", e);
                call_manager.handle_call_failure(call_id_for_error, e.to_string()).await;
            }
        });

        Ok(call_id)
    }

    pub async fn answer_call(&self, call_id: String) -> Result<(), CallManagerError> {
        let mut calls = self.active_calls.write().await;
        if let Some(active_call) = calls.get_mut(&call_id) {
            // Cancel timeout if it exists
            if let Some(handle) = active_call.timeout_handle.take() {
                handle.abort();
                log::info!("Cancelled incoming call timeout for answered call: {}", call_id);
            }
            
            active_call.info.status = CallStatus::Connected;
            active_call.info.start_time = Some(SystemTime::now());
            
            log::info!("Answering call: {}", call_id);
            
            // Release the lock before emitting events and starting timers
            drop(calls);
            
            // Start duration timer for connected call
            self.start_duration_timer(call_id.clone()).await;
            
            // Start quality monitoring
            self.start_quality_monitoring(call_id.clone()).await;
            
            // Emit call status event
            self.emit_call_status_event(CallStatusEvent {
                call_id: call_id.clone(),
                status: CallStatus::Connected,
                duration: Some(0),
            }).await;
            
            // TODO: Implement actual call answer using EZK SIP library
            // This would involve sending a 200 OK response to the INVITE
            
            Ok(())
        } else {
            Err(CallManagerError::CallNotFound(call_id))
        }
    }

    pub async fn reject_call(&self, call_id: String) -> Result<(), CallManagerError> {
        let mut calls = self.active_calls.write().await;
        if let Some(active_call) = calls.get_mut(&call_id) {
            // Cancel timeout if it exists
            if let Some(handle) = active_call.timeout_handle.take() {
                handle.abort();
                log::info!("Cancelled incoming call timeout for rejected call: {}", call_id);
            }
            
            active_call.info.status = CallStatus::Ended;
            
            log::info!("Rejecting call: {}", call_id);
            
            // Release the lock before emitting events
            drop(calls);
            
            // Emit call status event
            self.emit_call_status_event(CallStatusEvent {
                call_id: call_id.clone(),
                status: CallStatus::Ended,
                duration: None,
            }).await;
            
            // Save call to history
            self.save_call_to_history(&call_id).await;
            
            // TODO: Implement actual call rejection using EZK SIP library
            // This would involve sending a 486 Busy Here or 603 Decline response
            
            Ok(())
        } else {
            Err(CallManagerError::CallNotFound(call_id))
        }
    }

    pub async fn hangup_call(&self, call_id: String) -> Result<(), CallManagerError> {
        let mut calls = self.active_calls.write().await;
        if let Some(active_call) = calls.get_mut(&call_id) {
            // Cancel timeout if it exists
            if let Some(handle) = active_call.timeout_handle.take() {
                handle.abort();
                log::info!("Cancelled timeout for hung up call: {}", call_id);
            }
            
            // Cancel duration timer if it exists
            if let Some(handle) = active_call.duration_timer.take() {
                handle.abort();
                log::info!("Cancelled duration timer for hung up call: {}", call_id);
            }
            
            active_call.info.status = CallStatus::Ended;
            let duration = if let Some(start_time) = active_call.info.start_time {
                Some(SystemTime::now().duration_since(start_time).unwrap_or_default())
            } else {
                None
            };
            active_call.info.duration = duration;
            
            log::info!("Hanging up call: {}", call_id);
            
            // Release the lock before emitting events
            drop(calls);
            
            // Emit call status event
            self.emit_call_status_event(CallStatusEvent {
                call_id: call_id.clone(),
                status: CallStatus::Ended,
                duration: duration.map(|d| d.as_secs()),
            }).await;
            
            // Save call to history
            self.save_call_to_history(&call_id).await;
            
            // TODO: Implement actual call hangup using EZK SIP library
            // This would involve sending a BYE request
            
            Ok(())
        } else {
            Err(CallManagerError::CallNotFound(call_id))
        }
    }

    pub async fn mute_call(&self, call_id: String, muted: bool) -> Result<(), CallManagerError> {
        let mut calls = self.active_calls.write().await;
        if let Some(active_call) = calls.get_mut(&call_id) {
            active_call.is_muted = muted;
            
            log::info!("Setting mute for call {}: {}", call_id, muted);
            
            // Update quality metrics to reflect mute state
            if muted {
                active_call.quality_metrics.input_level = 0.0;
            }
            
            // Release lock before emitting events
            drop(calls);
            
            // Emit audio status event
            self.emit_audio_status_event(AudioStatusEvent {
                call_id: call_id.clone(),
                muted,
                volume_level: 1.0, // Default volume level
            }).await;
            
            // TODO: Implement actual mute functionality using audio manager
            
            Ok(())
        } else {
            Err(CallManagerError::CallNotFound(call_id))
        }
    }

    pub async fn get_active_calls(&self) -> HashMap<String, CallInfo> {
        let calls = self.active_calls.read().await;
        calls.iter().map(|(id, active_call)| (id.clone(), active_call.info.clone())).collect()
    }

    pub async fn get_call_info(&self, call_id: &str) -> Option<CallInfo> {
        let calls = self.active_calls.read().await;
        calls.get(call_id).map(|active_call| active_call.info.clone())
    }

    pub async fn handle_incoming_call(&self, caller_number: String, caller_name: Option<String>) -> String {
        let mut counter = self.call_counter.write().await;
        *counter += 1;
        let call_id = format!("call_{}", *counter);
        drop(counter);

        log::info!("Incoming call from {} with ID: {}", caller_number, call_id);

        let call_info = CallInfo {
            id: call_id.clone(),
            remote_number: caller_number.clone(),
            remote_name: caller_name.clone(),
            direction: CallDirection::Inbound,
            status: CallStatus::Ringing,
            start_time: Some(SystemTime::now()),
            duration: None,
        };

        let active_call = ActiveCall {
            info: call_info,
            sip_call: None,
            is_muted: false,
            timeout_handle: None,
            duration_timer: None,
            quality_metrics: CallQualityMetrics::default(),
        };

        self.active_calls.write().await.insert(call_id.clone(), active_call);

        // Emit incoming call event
        self.emit_incoming_call_event(IncomingCallEvent {
            call_id: call_id.clone(),
            caller_number: caller_number.clone(),
            caller_name: caller_name.clone(),
        }).await;

        // Start incoming call timeout
        self.start_incoming_call_timeout(call_id.clone()).await;

        // Play ringtone or show system notification
        self.show_incoming_call_notification(&caller_number, caller_name.as_deref()).await;

        call_id
    }

    // Event emission methods
    async fn emit_incoming_call_event(&self, event: IncomingCallEvent) {
        if let Some(app_handle) = self.app_handle.read().await.as_ref() {
            if let Err(e) = app_handle.emit("incoming-call", &event) {
                log::error!("Failed to emit incoming call event: {}", e);
            }
        }
    }

    async fn emit_call_status_event(&self, event: CallStatusEvent) {
        if let Some(app_handle) = self.app_handle.read().await.as_ref() {
            if let Err(e) = app_handle.emit("call-status", &event) {
                log::error!("Failed to emit call status event: {}", e);
            }
        }
    }

    async fn emit_audio_status_event(&self, event: AudioStatusEvent) {
        if let Some(app_handle) = self.app_handle.read().await.as_ref() {
            if let Err(e) = app_handle.emit("audio-status", &event) {
                log::error!("Failed to emit audio status event: {}", e);
            }
        }
    }

    // SIP integration methods
    async fn initiate_sip_call(
        &self,
        call_id: String,
        number: String,
        sip_manager: Arc<crate::sip_manager::SipManager>,
        audio_manager: Arc<crate::audio_manager::AudioManager>
    ) -> Result<(), CallManagerError> {
        log::info!("Initiating SIP call to {} for call ID: {}", number, call_id);

        // Get the SIP endpoint from the SIP manager
        let endpoint_lock = sip_manager.get_endpoint();
        let endpoint_guard = endpoint_lock.read().await;
        
        if let Some(_endpoint) = endpoint_guard.as_ref() {
            // Create SDP session for media negotiation
            let _sdp_session = self.create_sdp_session().await?;
            
            // Get SIP configuration for authentication
            // TODO: Get actual credentials from SIP manager
            let mut credentials = DigestCredentials::new();
            // This is a placeholder - in real implementation, get from SIP manager
            credentials.add_for_realm("example.com", DigestUser::new("user", "pass"));
            
            // Create the call using the registration
            // TODO: Get actual registration from SIP manager and make the call
            log::info!("SIP call setup initiated for {}", number);
            
            // Start audio stream for the call
            if let Err(e) = audio_manager.start_audio_stream(&call_id).await {
                log::error!("Failed to start audio stream for call {}: {}", call_id, e);
                return Err(CallManagerError::MediaError(format!("Audio stream failed: {}", e)));
            }
            
            // Update call status to indicate SIP processing
            self.update_call_status(&call_id, CallStatus::Ringing).await;
            
            Ok(())
        } else {
            Err(CallManagerError::SipError("No SIP endpoint available".to_string()))
        }
    }

    async fn create_sdp_session(&self) -> Result<SdpSession, CallManagerError> {
        let mut sdp_cfg = SdpSessionConfig::default();
        // Use traditional RTP/AVP to avoid DTLS-SRTP/AVPF negotiation failures
        sdp_cfg.offer_transport = RtcTransportType::Rtp;
        sdp_cfg.offer_avpf = false;
        // Set RTCP mux policy to negotiate
        sdp_cfg.rtcp_mux_policy = RtcpMuxPolicy::Negotiate;
        
        let context = OpenSslContext::try_new()
            .map_err(|e| CallManagerError::MediaError(format!("Failed to create OpenSSL context: {}", e)))?;
        
        // Use a default local IP - in production this should be detected
        let local_ip = "127.0.0.1".parse()
            .map_err(|e| CallManagerError::MediaError(format!("Invalid local IP: {}", e)))?;
        
        let mut sdp_session = SdpSession::new(context, local_ip, sdp_cfg);

        // Define audio codecs
        let audio = sdp_session
            .add_local_media(
                Codecs::new(MediaType::Audio)
                    .with_codec(Codec::PCMU)
                    .with_codec(Codec::PCMA)
                    .with_dtmf(),
                Direction::SendRecv,
            )
            .ok_or_else(|| CallManagerError::MediaError("Failed to add audio media".to_string()))?;

        // Add the audio stream
        sdp_session.add_media(audio, Direction::SendRecv);

        Ok(sdp_session)
    }

    async fn update_call_status(&self, call_id: &str, status: CallStatus) {
        let mut calls = self.active_calls.write().await;
        if let Some(active_call) = calls.get_mut(call_id) {
            active_call.info.status = status.clone();
            
            let duration = if let Some(start_time) = active_call.info.start_time {
                Some(SystemTime::now().duration_since(start_time).unwrap_or_default().as_secs())
            } else {
                None
            };

            // Emit status update
            drop(calls); // Release the lock before emitting
            self.emit_call_status_event(CallStatusEvent {
                call_id: call_id.to_string(),
                status,
                duration,
            }).await;
        }
    }

    async fn handle_call_failure(&self, call_id: String, error: String) {
        log::error!("Call {} failed: {}", call_id, error);
        
        let mut calls = self.active_calls.write().await;
        if let Some(active_call) = calls.get_mut(&call_id) {
            active_call.info.status = CallStatus::Failed;
            
            // Cancel timeout if it exists
            if let Some(handle) = active_call.timeout_handle.take() {
                handle.abort();
            }
        }
        drop(calls);

        // Emit failure event
        self.emit_call_status_event(CallStatusEvent {
            call_id,
            status: CallStatus::Failed,
            duration: None,
        }).await;
    }

    async fn start_incoming_call_timeout(&self, call_id: String) {
        const INCOMING_CALL_TIMEOUT: Duration = Duration::from_secs(30); // 30 seconds timeout
        
        let call_manager = Arc::new(self.clone());
        let timeout_call_id = call_id.clone();
        
        let timeout_handle = tokio::spawn(async move {
            sleep(INCOMING_CALL_TIMEOUT).await;
            
            log::info!("Incoming call {} timed out, auto-rejecting", timeout_call_id);
            
            // Auto-reject the call due to timeout
            if let Err(e) = call_manager.reject_call(timeout_call_id.clone()).await {
                log::error!("Failed to auto-reject timed out call {}: {}", timeout_call_id, e);
            }
            
            // Emit timeout event
            call_manager.emit_call_status_event(CallStatusEvent {
                call_id: timeout_call_id,
                status: CallStatus::Ended,
                duration: None,
            }).await;
        });
        
        // Store the timeout handle
        let mut calls = self.active_calls.write().await;
        if let Some(active_call) = calls.get_mut(&call_id) {
            active_call.timeout_handle = Some(timeout_handle);
        }
    }

    async fn show_incoming_call_notification(&self, caller_number: &str, caller_name: Option<&str>) {
        let display_name = caller_name.unwrap_or(caller_number);
        
        log::info!("Showing incoming call notification for: {}", display_name);
        
        // For now, we'll just log the notification
        // In a full implementation, this would:
        // 1. Show a system notification using the OS notification system
        // 2. Play a ringtone sound file
        // 3. Flash the window or bring it to front
        
        // Emit a notification event that the frontend can handle
        if let Some(app_handle) = self.app_handle.read().await.as_ref() {
            let notification_data = serde_json::json!({
                "type": "incoming_call_notification",
                "caller_number": caller_number,
                "caller_name": caller_name,
                "message": format!("Incoming call from {}", display_name)
            });
            
            if let Err(e) = app_handle.emit("system-notification", &notification_data) {
                log::error!("Failed to emit system notification: {}", e);
            }
        }
    }

    pub async fn cancel_incoming_call_timeout(&self, call_id: &str) {
        let mut calls = self.active_calls.write().await;
        if let Some(active_call) = calls.get_mut(call_id) {
            if let Some(handle) = active_call.timeout_handle.take() {
                handle.abort();
                log::info!("Cancelled incoming call timeout for call: {}", call_id);
            }
        }
    }

    // Duration timer functionality
    async fn start_duration_timer(&self, call_id: String) {
        let call_manager = Arc::new(self.clone());
        let timer_call_id = call_id.clone();
        
        let duration_handle = tokio::spawn(async move {
            let mut elapsed_seconds = 0u64;
            
            loop {
                sleep(Duration::from_secs(1)).await;
                elapsed_seconds += 1;
                
                // Check if call still exists and is connected
                let calls = call_manager.active_calls.read().await;
                if let Some(active_call) = calls.get(&timer_call_id) {
                    if active_call.info.status != CallStatus::Connected {
                        break; // Call is no longer connected, stop timer
                    }
                } else {
                    break; // Call no longer exists, stop timer
                }
                drop(calls);
                
                // Emit duration update every second
                call_manager.emit_call_duration_event(CallDurationEvent {
                    call_id: timer_call_id.clone(),
                    duration: elapsed_seconds,
                }).await;
            }
            
            log::info!("Duration timer stopped for call: {}", timer_call_id);
        });
        
        // Store the duration timer handle
        let mut calls = self.active_calls.write().await;
        if let Some(active_call) = calls.get_mut(&call_id) {
            active_call.duration_timer = Some(duration_handle);
        }
    }

    // Quality monitoring functionality
    async fn start_quality_monitoring(&self, call_id: String) {
        let call_manager = Arc::new(self.clone());
        let quality_call_id = call_id.clone();
        
        tokio::spawn(async move {
            loop {
                sleep(Duration::from_secs(5)).await; // Update quality metrics every 5 seconds
                
                // Check if call still exists and is connected
                let mut calls = call_manager.active_calls.write().await;
                if let Some(active_call) = calls.get_mut(&quality_call_id) {
                    if active_call.info.status != CallStatus::Connected {
                        break; // Call is no longer connected, stop monitoring
                    }
                    
                    // Update quality metrics (simulated for now)
                    active_call.quality_metrics.input_level = if active_call.is_muted { 0.0 } else { 0.7 };
                    active_call.quality_metrics.output_level = 0.8;
                    active_call.quality_metrics.packet_loss_rate = 0.01; // 1% packet loss
                    active_call.quality_metrics.jitter = 20.0; // 20ms jitter
                    active_call.quality_metrics.round_trip_time = Some(50); // 50ms RTT
                    active_call.quality_metrics.packets_sent += 50; // Simulate packet counts
                    active_call.quality_metrics.packets_received += 49;
                    active_call.quality_metrics.packets_lost += 1;
                    active_call.quality_metrics.bytes_sent += 8000; // Simulate byte counts
                    active_call.quality_metrics.bytes_received += 7800;
                    
                    let metrics = active_call.quality_metrics.clone();
                    drop(calls);
                    
                    // Emit quality update
                    call_manager.emit_call_quality_event(CallQualityEvent {
                        call_id: quality_call_id.clone(),
                        metrics,
                    }).await;
                } else {
                    break; // Call no longer exists, stop monitoring
                }
            }
            
            log::info!("Quality monitoring stopped for call: {}", quality_call_id);
        });
    }

    // Handle remote party hangup
    pub async fn handle_remote_hangup(&self, call_id: String) -> Result<(), CallManagerError> {
        log::info!("Handling remote hangup for call: {}", call_id);
        
        let mut calls = self.active_calls.write().await;
        if let Some(active_call) = calls.get_mut(&call_id) {
            // Cancel all timers
            if let Some(handle) = active_call.timeout_handle.take() {
                handle.abort();
            }
            if let Some(handle) = active_call.duration_timer.take() {
                handle.abort();
            }
            
            active_call.info.status = CallStatus::Ended;
            let duration = if let Some(start_time) = active_call.info.start_time {
                Some(SystemTime::now().duration_since(start_time).unwrap_or_default())
            } else {
                None
            };
            active_call.info.duration = duration;
            
            // Release the lock before emitting events
            drop(calls);
            
            // Emit call status event
            self.emit_call_status_event(CallStatusEvent {
                call_id: call_id.clone(),
                status: CallStatus::Ended,
                duration: duration.map(|d| d.as_secs()),
            }).await;
            
            // Save call to history
            self.save_call_to_history(&call_id).await;
            
            // TODO: Clean up audio streams and SIP resources
            
            Ok(())
        } else {
            Err(CallManagerError::CallNotFound(call_id))
        }
    }

    // Get call quality metrics
    pub async fn get_call_quality_metrics(&self, call_id: &str) -> Option<CallQualityMetrics> {
        let calls = self.active_calls.read().await;
        calls.get(call_id).map(|active_call| active_call.quality_metrics.clone())
    }

    // Save call to history
    async fn save_call_to_history(&self, call_id: &str) {
        let calls = self.active_calls.read().await;
        if let Some(active_call) = calls.get(call_id) {
            if let Some(history_manager) = self.call_history_manager.read().await.as_ref() {
                let call_record = crate::call_history::CallRecord::from(active_call.info.clone());
                if let Err(e) = history_manager.add_call_record(call_record).await {
                    log::error!("Failed to save call {} to history: {}", call_id, e);
                } else {
                    log::info!("Successfully saved call {} to history", call_id);
                }
            } else {
                log::warn!("Call history manager not available, cannot save call {}", call_id);
            }
        }
    }

    // Additional event emission methods
    async fn emit_call_duration_event(&self, event: CallDurationEvent) {
        if let Some(app_handle) = self.app_handle.read().await.as_ref() {
            if let Err(e) = app_handle.emit("call-duration", &event) {
                log::error!("Failed to emit call duration event: {}", e);
            }
        }
    }

    async fn emit_call_quality_event(&self, event: CallQualityEvent) {
        if let Some(app_handle) = self.app_handle.read().await.as_ref() {
            if let Err(e) = app_handle.emit("call-quality", &event) {
                log::error!("Failed to emit call quality event: {}", e);
            }
        }
    }
}

impl Default for CallManager {
    fn default() -> Self {
        Self::new()
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::sip_manager::SipManager;
    use std::sync::Arc;

    #[tokio::test]
    async fn test_call_manager_creation() {
        let call_manager = CallManager::new();
        
        // Test initial state
        let active_calls = call_manager.get_active_calls().await;
        assert!(active_calls.is_empty());
    }

    #[tokio::test]
    async fn test_call_info_retrieval() {
        let call_manager = CallManager::new();
        
        // Test getting non-existent call
        let call_info = call_manager.get_call_info("non_existent").await;
        assert!(call_info.is_none());
    }

    #[tokio::test]
    async fn test_incoming_call_handling() {
        let call_manager = CallManager::new();
        
        // Test handling incoming call
        let call_id = call_manager.handle_incoming_call(
            "1234567890".to_string(),
            Some("Test Caller".to_string())
        ).await;
        
        // Verify call was added
        let call_info = call_manager.get_call_info(&call_id).await;
        assert!(call_info.is_some());
        
        let call = call_info.unwrap();
        assert_eq!(call.remote_number, "1234567890");
        assert_eq!(call.remote_name, Some("Test Caller".to_string()));
        assert_eq!(call.direction, CallDirection::Inbound);
        assert_eq!(call.status, CallStatus::Ringing);
    }

    #[tokio::test]
    async fn test_call_status_updates() {
        let call_manager = CallManager::new();
        
        // Create an incoming call
        let call_id = call_manager.handle_incoming_call(
            "1234567890".to_string(),
            None
        ).await;
        
        // Test answering the call
        let result = call_manager.answer_call(call_id.clone()).await;
        assert!(result.is_ok());
        
        // Verify status was updated
        let call_info = call_manager.get_call_info(&call_id).await;
        assert!(call_info.is_some());
        assert_eq!(call_info.unwrap().status, CallStatus::Connected);
        
        // Test hanging up the call
        let result = call_manager.hangup_call(call_id.clone()).await;
        assert!(result.is_ok());
        
        // Verify status was updated
        let call_info = call_manager.get_call_info(&call_id).await;
        assert!(call_info.is_some());
        assert_eq!(call_info.unwrap().status, CallStatus::Ended);
    }

    #[tokio::test]
    async fn test_mute_functionality() {
        let call_manager = CallManager::new();
        
        // Create an incoming call and answer it
        let call_id = call_manager.handle_incoming_call(
            "1234567890".to_string(),
            None
        ).await;
        
        let _ = call_manager.answer_call(call_id.clone()).await;
        
        // Test muting
        let result = call_manager.mute_call(call_id.clone(), true).await;
        assert!(result.is_ok());
        
        // Test unmuting
        let result = call_manager.mute_call(call_id.clone(), false).await;
        assert!(result.is_ok());
    }

    #[tokio::test]
    async fn test_call_not_found_errors() {
        let call_manager = CallManager::new();
        
        // Test operations on non-existent call
        let result = call_manager.answer_call("non_existent".to_string()).await;
        assert!(result.is_err());
        assert!(matches!(result.unwrap_err(), CallManagerError::CallNotFound(_)));
        
        let result = call_manager.reject_call("non_existent".to_string()).await;
        assert!(result.is_err());
        assert!(matches!(result.unwrap_err(), CallManagerError::CallNotFound(_)));
        
        let result = call_manager.hangup_call("non_existent".to_string()).await;
        assert!(result.is_err());
        assert!(matches!(result.unwrap_err(), CallManagerError::CallNotFound(_)));
        
        let result = call_manager.mute_call("non_existent".to_string(), true).await;
        assert!(result.is_err());
        assert!(matches!(result.unwrap_err(), CallManagerError::CallNotFound(_)));
    }

    #[tokio::test]
    async fn test_make_call_basic() {
        let call_manager = CallManager::new();
        let sip_manager = Arc::new(SipManager::new());
        let audio_manager = Arc::new(crate::audio_manager::AudioManager::new().unwrap());
        
        // Test making a call (will fail due to no SIP endpoint, but should create call entry)
        let result = call_manager.make_call("1234567890".to_string(), sip_manager, audio_manager).await;
        assert!(result.is_ok());
        
        let call_id = result.unwrap();
        
        // Verify call was created
        let call_info = call_manager.get_call_info(&call_id).await;
        assert!(call_info.is_some());
        
        let call = call_info.unwrap();
        assert_eq!(call.remote_number, "1234567890");
        assert_eq!(call.direction, CallDirection::Outbound);
        assert_eq!(call.status, CallStatus::Ringing);
    }

    #[tokio::test]
    async fn test_remote_hangup_handling() {
        let call_manager = CallManager::new();
        
        // Create an incoming call and answer it
        let call_id = call_manager.handle_incoming_call(
            "1234567890".to_string(),
            None
        ).await;
        
        let _ = call_manager.answer_call(call_id.clone()).await;
        
        // Test remote hangup
        let result = call_manager.handle_remote_hangup(call_id.clone()).await;
        assert!(result.is_ok());
        
        // Verify call status was updated
        let call_info = call_manager.get_call_info(&call_id).await;
        assert!(call_info.is_some());
        assert_eq!(call_info.unwrap().status, CallStatus::Ended);
    }

    #[tokio::test]
    async fn test_call_quality_metrics() {
        let call_manager = CallManager::new();
        
        // Create an incoming call and answer it
        let call_id = call_manager.handle_incoming_call(
            "1234567890".to_string(),
            None
        ).await;
        
        let _ = call_manager.answer_call(call_id.clone()).await;
        
        // Get quality metrics
        let metrics = call_manager.get_call_quality_metrics(&call_id).await;
        assert!(metrics.is_some());
        
        let metrics = metrics.unwrap();
        assert_eq!(metrics.input_level, 0.0); // Should be 0 initially
        assert_eq!(metrics.output_level, 0.0);
        assert_eq!(metrics.packet_loss_rate, 0.0);
    }

    #[tokio::test]
    async fn test_call_duration_tracking() {
        let call_manager = CallManager::new();
        
        // Create an incoming call and answer it
        let call_id = call_manager.handle_incoming_call(
            "1234567890".to_string(),
            None
        ).await;
        
        let _ = call_manager.answer_call(call_id.clone()).await;
        
        // Wait a bit to let duration accumulate
        tokio::time::sleep(tokio::time::Duration::from_millis(100)).await;
        
        // Hang up the call
        let _ = call_manager.hangup_call(call_id.clone()).await;
        
        // Verify call has duration
        let call_info = call_manager.get_call_info(&call_id).await;
        assert!(call_info.is_some());
        
        let call = call_info.unwrap();
        assert!(call.duration.is_some());
        assert!(call.duration.unwrap().as_millis() >= 100);
    }
}